{
    "cells": [
        {
            "cell_type": "markdown",
            "id": "c554e753",
            "metadata": {},
            "source": [
                "# Interactive mapping\n",
                "\n",
                "Alongside static plots, `geopandas` can create interactive maps based on the [folium](https://python-visualization.github.io/folium/) library.\n",
                "\n",
                "Creating maps for interactive exploration mirrors the API of static [plots](../reference/api/geopandas.GeoDataFrame.plot.html) in an [explore()](../reference/api/geopandas.GeoDataFrame.explore.html) method of a GeoSeries or GeoDataFrame.\n",
                "\n",
                "Loading some example data:"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "id": "caf2fbd5",
            "metadata": {},
            "outputs": [],
            "source": [
                "import geopandas\n",
                "import geodatasets\n",
                "\n",
                "nybb = geopandas.read_file(geodatasets.get_path(\"nybb\"))\n",
                "chicago = geopandas.read_file(geodatasets.get_path(\"geoda.chicago_commpop\"))\n",
                "groceries = geopandas.read_file(geodatasets.get_path(\"geoda.groceries\")).explode(ignore_index=True)"
            ]
        },
        {
            "cell_type": "markdown",
            "id": "56bf1bcf",
            "metadata": {},
            "source": [
                "The simplest option is to use `GeoDataFrame.explore()`:"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "id": "6b484ecc",
            "metadata": {},
            "outputs": [],
            "source": [
                "nybb.explore()"
            ]
        },
        {
            "cell_type": "markdown",
            "id": "7a797389",
            "metadata": {},
            "source": [
                "Interactive plotting offers largely the same customisation as static one plus some features on top of that. Check the code below which plots a customised choropleth map. You can use `\"BoroName\"` column with NY boroughs names as an input of the choropleth, show (only) its name in the tooltip on hover but show all values on click. You can also pass custom background tiles (either a name supported by folium, a name recognized by `xyzservices.providers.query_name()`, XYZ URL or `xyzservices.TileProvider` object), specify colormap (all supported by `matplotlib`) and specify black outline."
            ]
        },
        {
            "cell_type": "markdown",
            "id": "798bf532",
            "metadata": {},
            "source": [
                "<div class=\"alert alert-info\">\n",
                "Note\n",
                "\n",
                "Note that the GeoDataFrame needs to have a CRS set if you want to use background tiles.\n",
                "</div>"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "id": "94b4ff24",
            "metadata": {},
            "outputs": [],
            "source": [
                "nybb.explore(\n",
                "    column=\"BoroName\",  # make choropleth based on \"BoroName\" column\n",
                "    tooltip=\"BoroName\",  # show \"BoroName\" value in tooltip (on hover)\n",
                "    popup=True,  # show all values in popup (on click)\n",
                "    tiles=\"CartoDB positron\",  # use \"CartoDB positron\" tiles\n",
                "    cmap=\"Set1\",  # use \"Set1\" matplotlib colormap\n",
                "    style_kwds=dict(color=\"black\"),  # use black outline\n",
                ")"
            ]
        },
        {
            "cell_type": "markdown",
            "id": "5a10291e",
            "metadata": {},
            "source": [
                "The `explore()` method returns a `folium.Map` object, which can also be passed directly (as you do with `ax` in `plot()`). You can then use folium functionality directly on the resulting map. In the example below, you can plot two GeoDataFrames on the same map and add layer control using folium. You can also add additional tiles allowing you to change the background directly in the map."
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "id": "cba9970b",
            "metadata": {},
            "outputs": [],
            "source": [
                "import folium\n",
                "\n",
                "m = chicago.explore(\n",
                "    column=\"POP2010\",  # make choropleth based on \"POP2010\" column\n",
                "    scheme=\"naturalbreaks\",  # use mapclassify's natural breaks scheme\n",
                "    legend=True,  # show legend\n",
                "    k=10,  # use 10 bins\n",
                "    tooltip=False,  # hide tooltip\n",
                "    popup=[\"POP2010\", \"POP2000\"],  # show popup (on-click)\n",
                "    legend_kwds=dict(colorbar=False),  # do not use colorbar\n",
                "    name=\"chicago\",  # name of the layer in the map\n",
                ")\n",
                "\n",
                "groceries.explore(\n",
                "    m=m,  # pass the map object\n",
                "    color=\"red\",  # use red color on all points\n",
                "    marker_kwds=dict(radius=5, fill=True),  # make marker radius 10px with fill\n",
                "    tooltip=\"Address\",  # show \"name\" column in the tooltip\n",
                "    tooltip_kwds=dict(labels=False),  # do not show column label in the tooltip\n",
                "    name=\"groceries\",  # name of the layer in the map\n",
                ")\n",
                "\n",
                "folium.TileLayer(\"CartoDB positron\", show=False).add_to(\n",
                "    m\n",
                ")  # use folium to add alternative tiles\n",
                "folium.LayerControl().add_to(m)  # use folium to add layer control\n",
                "\n",
                "m  # show map"
            ]
        }
    ],
    "metadata": {
        "kernelspec": {
            "display_name": "Python 3 (ipykernel)",
            "language": "python",
            "name": "python3"
        },
        "language_info": {
            "codemirror_mode": {
                "name": "ipython",
                "version": 3
            },
            "file_extension": ".py",
            "mimetype": "text/x-python",
            "name": "python",
            "nbconvert_exporter": "python",
            "pygments_lexer": "ipython3",
            "version": "3.11.0"
        },
        "vscode": {
            "interpreter": {
                "hash": "b1fe2ae8565152c84d3dbd08488d3746f754c9bdf2de9b61cf939da5306d3793"
            }
        }
    },
    "nbformat": 4,
    "nbformat_minor": 5
}
